﻿using System;
using System.Net;
using System.Net.Sockets;
using System.Threading;


namespace AccessControl.FS84Test
{
	public class SocketManager
	{
		#region Fields

		private readonly string _ipString;
		private readonly int _port;
		private static SocketManager _instance;
		private readonly Socket _socket;

		#endregion

		#region Constructor

		private SocketManager(String ip, int port)
		{
			var ipAddress = IPAddress.Parse(ip);
			if (ipAddress != null)
			{
				var ipe = new IPEndPoint(ipAddress, port);
				_socket =
					new Socket(ipe.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
			}
			_ipString = ip;
			_port = port;
			_socket.Connect(_ipString, _port);
		}

		#endregion

		#region Properties

		public Socket CurrentSocket { get { return _socket; } }

		#endregion

		#region Public Methods

		public static SocketManager GetSocketManager(String ip, int port)
		{
			return _instance ?? (_instance = new SocketManager(ip, port));
		}

		public void Send(byte[] buffer)
		{
			byte nChksum = 0;
			for (var nIndex = 0; nIndex < 11; nIndex++)
				nChksum += buffer[nIndex];
			buffer[11] = nChksum;
			try
			{
				_socket.Send(buffer);

			}
			catch (SocketException ex)
			{
				if (ex.SocketErrorCode == SocketError.WouldBlock ||
					ex.SocketErrorCode == SocketError.IOPending ||
					ex.SocketErrorCode == SocketError.NoBufferSpaceAvailable)
				{
					Thread.Sleep(30);
					Send(buffer);
				}
				else
					throw;
			}

		}


		public byte[] Receive()
		{

			var buffer = new byte[] { 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d };
			byte nChksum = 0;
			for (var nIndex = 0; nIndex < 11; nIndex++)
				nChksum += buffer[nIndex];
			buffer[11] = nChksum;
			try
			{

				_socket.Receive(buffer);

			}
			catch (SocketException ex)
			{
				if (ex.SocketErrorCode == SocketError.WouldBlock ||
					ex.SocketErrorCode == SocketError.IOPending ||
					ex.SocketErrorCode == SocketError.NoBufferSpaceAvailable)
				{
					Thread.Sleep(30);
					buffer = Receive();
				}
				else
					throw;
			}
			return buffer;
		}

		#endregion

		#region Private Methods

		#endregion

	}
}
